package edu.buffalo.cse.cse486_586.simpledynamo;

import java.util.HashMap;
import java.util.Map;

import edu.buffalo.cse.cse486_586.simpledynamo.R;
import edu.buffalo.cse.cse486_586.simpledynamo.util.AppUtil;
import edu.buffalo.cse.cse486_586.simpledynamo.service.NetWorkService;
import android.app.Activity;
import android.content.ComponentName;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.database.Cursor;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;

public class MainActivity extends Activity {
	// Debugging
	private static final String TAG = "MainActivity";
	private static final boolean D = true;

	// Layout Views
	private ListView msgList;
	// required button
	private Button put1Button;
	private Button put2Button;
	private Button put3Button;
	private Button getButton;
	private Button dumpButton;
	// self defined button
	private Button addButton;
	private Button debugButton;
	private Button cleanButton;

	// Array adapter for the conversation thread
	private ArrayAdapter<String> msgListAdapter;

	// incoming Messenger for communicating with service.
	final private Messenger incommingMessager = new Messenger(
			new MessagerHandler());
	// outgoing Messenger for communicating with service
	private Messenger outgoingMessager = null;
	// Flag indicating whether we have called bind on the service.
	boolean mIsBound;

	// Handler of messages from binded service.
	class MessagerHandler extends Handler {
		@Override
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case AppUtil.MSG_UPDATE_VIEWLIST:
				msgListAdapter.add(msg.getData().getString(AppUtil.DISPLAY_RESULT));
				break;
			case AppUtil.MSG_PUT_CASE:
				String result = msg.getData().getString(AppUtil.RESULT);
				msgListAdapter.add(result);
				break;
			case AppUtil.MSG_DISPLAY_TOAST :
				 Context context = getApplicationContext();
				 CharSequence text = msg.getData().getString(AppUtil.DISPLAY_RESULT);
				 int duration = Toast.LENGTH_SHORT;
				
				 Toast toast = Toast.makeText(context, text, duration);
				 toast.show();
				 break;
			default:
				super.handleMessage(msg);
				break;
			}
		}
	}

	/**
	 * Class for interacting with the main interface of the service.
	 */
	public NetWorkConnection mConnection = new NetWorkConnection();

	class NetWorkConnection implements ServiceConnection {
		public void onServiceConnected(ComponentName className, IBinder service) {
			// This is called when the connection with the service has been
			// established, giving us the service object we can use to
			// interact with the service. We are communicating with our
			// service through an IDL interface, so get a client-side
			// representation of that from the raw service object.
			outgoingMessager = new Messenger(service);
			Log.d(TAG, "Attached.");

			// We want to monitor the service for as long as we are
			// connected to it.
			try {
				Message msg = Message.obtain(null, AppUtil.MSG_REGISTER_CLIENT);
				msg.replyTo = incommingMessager;
				outgoingMessager.send(msg);
			} catch (RemoteException e) {
				Log.e(TAG, "Exception", e);
			}
		}

		public void onServiceDisconnected(ComponentName className) {
			// This is called when the connection with the service has been
			// unexpectedly disconnected -- that is, its process crashed.
			outgoingMessager = null;
			Log.d(TAG, "detached.");
		}
	}

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		// binding activity with service
		setupChatView();

		if (!mIsBound) {
			bindService(new Intent(this, NetWorkService.class), mConnection,
					Context.BIND_AUTO_CREATE);
			mIsBound = true;
		}
	}

	@Override
	public void onStart() {
		super.onStart();
	}

	@Override
	protected void onDestroy() {
		super.onDestroy();

		if (mIsBound) {
			unbindService(mConnection);
		}
	}

	/*
	 * set message to service
	 */
	public void sendMessage(int message, Map<String, String> data) {
		try {
			Message msg = Message.obtain(null, message);
			android.os.Bundle b = new android.os.Bundle();

			if (data != null) {
				for (Map.Entry<String, String> item : data.entrySet()) {
					b.putString(item.getKey(), item.getValue());
				}
			}
			msg.setData(b);
			msg.replyTo = incommingMessager;
			outgoingMessager.send(msg);
		} catch (RemoteException e) {
			Log.e(TAG, "Exception", e);
		}
	}

	/*
	 * clean list view, but not delete the data in provider
	 */
	public void cleanScreen() {
		msgListAdapter.clear();
	}

	/*
	 * set up UI interface once the activity start.
	 */
	private void setupChatView() {
		// view list
		msgList = (ListView) findViewById(R.id.msgList);
		msgListAdapter = new ArrayAdapter<String>(this, R.layout.list_msg);
		try {
			//insertData();
			queryData();
		} catch (Exception e) {
			Log.d(TAG, "Exception", e);
		}
		msgList.setAdapter(msgListAdapter);

		// required button
		put1Button = (Button) findViewById(R.id.put1tButton);
		put1Button.setOnClickListener(new PutListener(AppUtil.PUT_1));
		put2Button = (Button) findViewById(R.id.put2Button);
		put2Button.setOnClickListener(new PutListener(AppUtil.PUT_2));
		put3Button = (Button) findViewById(R.id.put3Button);
		put3Button.setOnClickListener(new PutListener(AppUtil.PUT_3));

		getButton = (Button) findViewById(R.id.getButton);
		getButton.setOnClickListener(new GetListener());
		dumpButton = (Button) findViewById(R.id.dumpButton);
		dumpButton.setOnClickListener(new DumpListener());
		// self defined button
		debugButton = (Button) findViewById(R.id.debugButton);
		debugButton.setOnClickListener(new DebugListener());
		cleanButton = (Button) findViewById(R.id.cleanButton);
		cleanButton.setOnClickListener(new CleanListener());
	}

	public void display(String key, String value, String version) {
		String out = "key :" + key + "\nvalue :" + value + "\nversion :"
				+ version;
		msgListAdapter.add(out);
	}

//	private void insertData() {
//		ContentValues cv = new ContentValues();
//		cv.put(AppUtil.KeyValueTable.COL_PROVIDER_KEY, "msg0001");
//		cv.put(AppUtil.KeyValueTable.COL_PROVIDER_VALUE, "msg content 00001");
//		cv.put(AppUtil.KeyValueTable.COL_PROVIDER_VERSION, "0");
//		getContentResolver().insert(AppUtil.CONTENT_URI, cv);
//
//		cv.put(AppUtil.KeyValueTable.COL_PROVIDER_KEY, "msg0002");
//		cv.put(AppUtil.KeyValueTable.COL_PROVIDER_VALUE, "msg content 00002");
//		cv.put(AppUtil.KeyValueTable.COL_PROVIDER_VERSION, "0");
//		getContentResolver().insert(AppUtil.CONTENT_URI, cv);
//	}

	private void queryData() {
		Cursor c = getContentResolver().query(
				AppUtil.CONTENT_URI,
				new String[] { AppUtil.KeyValueTable.COL_ID,
						AppUtil.KeyValueTable.COL_PROVIDER_KEY,
						AppUtil.KeyValueTable.COL_PROVIDER_VALUE,
						AppUtil.KeyValueTable.COL_PROVIDER_VERSION }, null,
				null, null);

		if (c.moveToFirst()) {
			while (!c.isAfterLast()) {
				String out = "";
				out += "key : "
						+ c.getString(c
								.getColumnIndexOrThrow(AppUtil.KeyValueTable.COL_PROVIDER_KEY))
						+ "\n";
				out += "value : "
						+ c.getString(c
								.getColumnIndexOrThrow(AppUtil.KeyValueTable.COL_PROVIDER_VALUE))
						+ "\n";
				out += "version : "
						+ c.getString(c
								.getColumnIndexOrThrow(AppUtil.KeyValueTable.COL_PROVIDER_VERSION));
				msgListAdapter.add(out);
				c.moveToNext();
			}
		}
	}

	private class PutListener implements OnClickListener {
		private String valueString;

		public PutListener(String str) {
			this.valueString = str;
		}

		@Override
		public void onClick(View v) {
			Map<String, String> dataMap = new HashMap<String, String>();
			if (valueString.equals(AppUtil.PUT_1)) {
				dataMap.put(AppUtil.PUT_PRIFIX, AppUtil.PUT_1);
			} else if (valueString.equals(AppUtil.PUT_2)) {
				dataMap.put(AppUtil.PUT_PRIFIX, AppUtil.PUT_2);
			} else if (valueString.equals(AppUtil.PUT_3)) {
				dataMap.put(AppUtil.PUT_PRIFIX, AppUtil.PUT_3);
			}
			sendMessage(AppUtil.MSG_PUT_CASE, dataMap);
		}
	}

	/*
	 * retrieve ten keys, “0”, “1”, …, “9” with their corresponding values
	 */
	private class GetListener implements OnClickListener {
		@Override
		public void onClick(View v) {
			sendMessage(AppUtil.MSG_GET_CASE, null);
		}
	}

	/*
	 * dump all local storage
	 */
	private class DumpListener implements OnClickListener {
		@Override
		public void onClick(View v) {
			queryData();
		}
	}

	private class CleanListener implements OnClickListener {
		@Override
		public void onClick(View v) {
			getContentResolver().delete(AppUtil.CONTENT_URI, null, null);
			cleanScreen();
		}
	}

	private class DebugListener implements OnClickListener {
		@Override
		public void onClick(View v) {
			// delete all k-v in content provider
			msgListAdapter.clear();
		}
	}

	private class AddListener implements OnClickListener {
		@Override
		public void onClick(View v) {
		}
	}
}